package com.gzx.spring.apis.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.net.URLEncoder;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.gzx.risk.core.vo.credit.C9004;
import com.gzx.risk.core.vo.credit.C9005;
import com.gzx.risk.core.vo.v1.RuleQueryVO;
import com.gzx.spring.apis.enums.SignType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.util.Date;
import java.util.Map;

@Slf4j
public class HuarongUtil {
    private String privateKeyBase64;// rsa私钥
    private String publicKeyBase64;// rsa公钥
    private String desKey;// des盐key
    private String md5Key;// mk5key
    private String post_url_base;// 征信查询请求地址
    private String merchantId;// 机构编号

    public HuarongUtil privateKeyBase64(String privateKeyBase64) {
        this.privateKeyBase64 = privateKeyBase64;
        return this;
    }

    public HuarongUtil publicKeyBase64(String publicKeyBase64) {
        this.publicKeyBase64 = publicKeyBase64;
        return this;
    }

    public HuarongUtil desKey(String desKey) {
        this.desKey = desKey;
        return this;
    }

    public HuarongUtil md5Key(String md5Key) {
        this.md5Key = md5Key;
        return this;
    }

    public HuarongUtil post_url_base(String post_url_base) {
        this.post_url_base = post_url_base;
        return this;
    }

    public HuarongUtil merchantId(String merchantId) {
        this.merchantId = merchantId;
        return this;
    }

    private String exec(String queryType, Map<String, Object> parmMap, String serialNumber){
        URLEncoder.FRAGMENT.removeSafeCharacter('+');  // 高版本的hutool需要增加這個代碼。否則后端会签名不通过
        String resp = HttpUtil.post(String.format("%s/%s", post_url_base, queryType), parmMap, 60000);

        String requestNo = parmMap.get("requestNo").toString();
        JSONObject jsonObject = JSONUtil.parseObj(resp);
        String code = jsonObject.getStr("code");
        String message = jsonObject.getStr("message");
        String data = jsonObject.getStr("data");

        if (!"0000".equals(jsonObject.getStr("code"))) {
            log.error("{}-失败, serialNumber:{}, requestNo:{}, errorCode:{}, message:{}",
                    queryType, serialNumber, requestNo , code, message);
            return jsonObject.toString();
        }
        JSONObject JsonData = JSONUtil.parseObj(data);
        JsonData.set("requestNo", requestNo);
        jsonObject.set("data", JsonData);
        return jsonObject.toString();
    }

    /**
     * 综合电子认证授权
     *
     * @param c9004DTO
     * @return
     */
    public String C9004(C9004 c9004DTO){
        C9004 c9004 = new C9004();
        BeanUtils.copyProperties(c9004DTO,c9004);
        c9004.setRequestNo(RequestUtil.getRequestNo());
        c9004.setQueryName(SecureUtil.des(desKey.getBytes()).encryptBase64(c9004.getQueryName()));
        c9004.setQueryIdNo(SecureUtil.des(desKey.getBytes()).encryptBase64(c9004.getQueryIdNo()));
        c9004.setQueryPhone(SecureUtil.des(desKey.getBytes()).encryptBase64(c9004.getQueryPhone()));
//        c9004.setQueyCardNo(SecureUtil.des(desKey.getBytes()).encryptBase64(c9004.getAssetsFile()));
        c9004.setMerchantId(merchantId);
        c9004.setRiskQueryType("C9004");
        c9004.setQueryIdNoType("01");
        c9004.setQueryDate(DateUtil.format(new Date(), "yyyyMMdd"));
        c9004.setSignType(SignType.RSA1.getType());
        c9004.setAuthIndexId(generateAuthIndexId());
        Map<String, Object> beanToMap = BeanUtil.beanToMap(c9004);
        String signBase64 = getSignature(beanToMap);
        c9004.setSignature(signBase64);
        Map<String, Object> paramMap = BeanUtil.beanToMap(c9004);
        return exec("C9004", paramMap, null);
    }

    /**
     * 主动查询授权结果
     * @param serialNumber 授权流水号
     * @return
     */
    public String C9005(String serialNumber){
        C9005 c9005 = new C9005();
        c9005.setSerialNumber(serialNumber);
        c9005.setRequestNo(RequestUtil.getRequestNo());
        c9005.setMerchantId(merchantId);
        c9005.setRiskQueryType("C9005");
        c9005.setQueryDate(DateUtil.format(new Date(), "yyyyMMdd"));
        c9005.setSignType(SignType.RSA1.getType());
        Map<String, Object> beanToMap = BeanUtil.beanToMap(c9005);
        String signBase64 = getSignature(beanToMap);
        c9005.setSignature(signBase64);
        Map<String, Object> paramMap = BeanUtil.beanToMap(c9005);
        return exec("C9005",paramMap,serialNumber);
    }

    /**
     * 规则集查询
     * @param serialNumber 授权流水号
     * @return
     */
    public String R9003(String serialNumber){
        RuleQueryVO reqQuery = new RuleQueryVO();
        reqQuery.setSerialNumber(serialNumber);
        reqQuery.setRequestNo(RequestUtil.getRequestNo());
        reqQuery.setMerchantId(merchantId);
        reqQuery.setRiskQueryType("R9003");
        reqQuery.setQueryDate(DateUtil.format(new Date(), "yyyyMMdd"));
        reqQuery.setSignType(SignType.RSA1.getType());
        Map<String, Object> beanToMap = BeanUtil.beanToMap(reqQuery);
        String signBase64 = getSignature(beanToMap);
        reqQuery.setSignature(signBase64);
        Map<String, Object> paramMap = BeanUtil.beanToMap(reqQuery);
        return exec("R9003", paramMap,serialNumber);
    }

    private String getSignature(Map<String, Object> beanToMap) {
        beanToMap.remove("signature");
        // 初始化签名器，单例
        SignUtil.initSign(merchantId, privateKeyBase64, publicKeyBase64);
        return SignUtil.getRsa1Signature(beanToMap, merchantId);
    }

    private String generateAuthIndexId() {
        String uniqueId = "T" + System.currentTimeMillis();
        return uniqueId + "AND" + "0011000000000";
    }
}
